﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class ResourcesManager : UnitySingleton<ResourcesManager>
{
    //是否通过assetbundle加载资源
    public bool UsedAssetBundle = false;

    private bool mInit = false;
    private int mFrameCount = 0;
    private Request mCurrentRequest = null;
    private Queue<Request> mAllRequests = new Queue<Request>();

    //保存读取的Resource信息
    //private AssetInfoManager mAssetInfoManager = null;
    private Dictionary<string, string> mResources = new Dictionary<string, string>();
    //加载的资源信息
    private Dictionary<string, ResourceUnit> mLoadedResourceUnit = new Dictionary<string, ResourceUnit>();

    public delegate void HandleFinishLoad(ResourceUnit resource);
    public delegate void HandleFinishLoadLevel();
    public delegate void HandleFinishUnLoadLevel();
    private void Start()
    {

    }

    public void Init()
    {

        mInit = true;
    }

    public void Update()
    {
        if (!mInit)
            return;

        if (null == mCurrentRequest && mAllRequests.Count > 0)
            handleRequest();

        ++mFrameCount;
        if (mFrameCount == 300)
        {
            mFrameCount = 0;
        }
    }

    private void handleRequest()
    {
        //使用assetbundle打包功能
        if (UsedAssetBundle)
        {
            mCurrentRequest = mAllRequests.Dequeue();

            //相对Asset的完整资源路径
            string fileName = mCurrentRequest.mFileName;

            switch (mCurrentRequest.mRequestType)
            {
                case RequestType.LOAD:
                    {
                        switch (mCurrentRequest.mResourceType)
                        {
                            case ResourceType.ASSET:
                            case ResourceType.PREFAB:
                                {
                                    if (mLoadedResourceUnit.ContainsKey(fileName))
                                    {

                                        mCurrentRequest.mResourceAsyncOperation.mComplete = true;
                                        mCurrentRequest.mResourceAsyncOperation.mResource = mLoadedResourceUnit[fileName] as ResourceUnit;

                                        if (null != mCurrentRequest.mHandle)
                                            mCurrentRequest.mHandle(mLoadedResourceUnit[fileName] as ResourceUnit);
                                        handleResponse();
                                    }
                                    else
                                    {

                                    }
                                }
                                break;
                            case ResourceType.LEVELASSET:
                                {

                                }
                                break;
                            case ResourceType.LEVEL:
                                {
                                    //  
                                }
                                break;
                        }
                    }
                    break;
                case RequestType.UNLOAD:
                    {
                        if (!mLoadedResourceUnit.ContainsKey(fileName))
                            Debug.LogError("can not find " + fileName);
                        else
                        {

                        }
                        handleResponse();
                    }
                    break;
                case RequestType.LOADLEVEL:
                    {
                        StartCoroutine(_loadLevel(fileName, mCurrentRequest.mHandleLevel, ResourceType.LEVEL, mCurrentRequest.mResourceAsyncOperation));
                    }
                    break;
                case RequestType.UNLOADLEVEL:
                    {
                        if (!mLoadedResourceUnit.ContainsKey(fileName))
                            Debug.LogError("can not find level " + fileName);
                        else
                        {
                            if (null != mCurrentRequest.mHandleUnloadLevel)
                                mCurrentRequest.mHandleUnloadLevel();
                        }
                        handleResponse();
                    }
                    break;
            }
        }
        //不使用打包
        else
        {
            mCurrentRequest = mAllRequests.Dequeue();

            switch (mCurrentRequest.mRequestType)
            {
                case RequestType.LOAD:
                    {
                        switch (mCurrentRequest.mResourceType)
                        {
                            case ResourceType.ASSET:
                            case ResourceType.PREFAB:
                                {
                                    //暂时不处理，直接使用资源相对路径

                                }
                                break;
                            case ResourceType.LEVELASSET:
                                {

                                }
                                break;
                            case ResourceType.LEVEL:
                                {

                                }
                                break;
                        }
                    }
                    break;
                case RequestType.UNLOAD:
                    {
                        handleResponse();
                    }
                    break;
                case RequestType.LOADLEVEL:
                    {
                        StartCoroutine(_loadLevel(mCurrentRequest.mFileName, mCurrentRequest.mHandleLevel, ResourceType.LEVEL, mCurrentRequest.mResourceAsyncOperation));
                    }
                    break;
                case RequestType.UNLOADLEVEL:
                    {
                        if (null != mCurrentRequest.mHandleUnloadLevel)
                            mCurrentRequest.mHandleUnloadLevel();
                        handleResponse();
                    }
                    break;
            }
        }
    }

    private void handleResponse()
    {
        mCurrentRequest = null;
    }

    //传入Resources下相对路径名称 例如Resources/Game/Effect1    传入Game/Effect1
    public ResourceUnit loadImmediate(string filePathName, ResourceType resourceType, string archiveName = "Resources")
    {
        //使用assetbundle打包
        if (UsedAssetBundle)
        {
            //添加Resource
            string completePath = "Resources/" + filePathName;
            //加载本身预制件
            ResourceUnit unit = _LoadImmediate(completePath, resourceType);

            return unit;
        }
        //不使用
        else
        {
            Object asset = Resources.Load(filePathName);
            ResourceUnit resource = new ResourceUnit(null, 0, asset, null, resourceType);
            return resource;
        }

    }
    //加载场景
    public ResourceAsyncOperation loadLevel(string fileName, HandleFinishLoadLevel handle, string archiveName = "Level")
    {

        {
            ResourceAsyncOperation operation = new ResourceAsyncOperation(RequestType.LOADLEVEL);
            mAllRequests.Enqueue(new Request(fileName, ResourceType.LEVEL, handle, RequestType.LOADLEVEL, operation));
            return operation;
        }
    }

    private IEnumerator _loadLevel(string path, HandleFinishLoadLevel handle, ResourceType resourceType, ResourceAsyncOperation operation)
    {
        //使用assetbundle打包
        if (UsedAssetBundle)
        {
            //加载场景assetbundle     
            int scenAssetBundleSize = 0;
            byte[] binary = ResourceCommon.getAssetBundleFileBytes(path, ref scenAssetBundleSize);
            AssetBundle assetBundle = AssetBundle.LoadFromMemory(binary);
            if (!assetBundle)
                Debug.LogError("create scene assetbundle " + path + "in _LoadImmediate failed");

            //添加场景大小
            operation.mLoadDependencesAssetSize += scenAssetBundleSize;

            AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(ResourceCommon.getFileName(path, false));
            operation.asyncOperation = asyncOperation;
            yield return asyncOperation;

            handleResponse();

            operation.asyncOperation = null;
            operation.mComplete = true;
            operation.mResource = null;

            if (null != handle)
                handle();

        }
        //不使用
        else
        {
            ResourceUnit level = new ResourceUnit(null, 0, null, path, resourceType);

            //获取加载场景名称
            string sceneName = ResourceCommon.getFileName(path, true);
            AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneName);
            operation.asyncOperation = asyncOperation;
            yield return asyncOperation;

            handleResponse();

            operation.asyncOperation = null;
            operation.mComplete = true;

            if (null != handle)
                handle();
        }
    }

    //单个资源加载
    ResourceUnit _LoadImmediate(string fileName, ResourceType resourceType)
    {
        //没有该资源，加载
        if (!mLoadedResourceUnit.ContainsKey(fileName))
        {
            //资源大小
            int assetBundleSize = 0;
            byte[] binary = ResourceCommon.getAssetBundleFileBytes(fileName, ref assetBundleSize);
            AssetBundle assetBundle = AssetBundle.LoadFromMemory(binary);

            if (!assetBundle)
                Debug.LogError("create assetbundle " + fileName + "in _LoadImmediate failed");

            Object asset = assetBundle.LoadAsset(fileName);
            if (!asset)
                Debug.LogError("load assetbundle " + fileName + "in _LoadImmediate failed");

            ResourceUnit ru = new ResourceUnit(assetBundle, assetBundleSize, asset, fileName, resourceType);

            //添加到资源中
            mLoadedResourceUnit.Add(fileName, ru);

            return ru;
        }
        else
        {
            return mLoadedResourceUnit[fileName];
        }
    }
}





